﻿//////////////////////////////////////////////////////////////////////////////
//
//  Copyright © 1998-2024 Glodon Company Limited.  All rights reserved.
//
//  Use of this software is subject to the terms of the Glodon license
//  agreement provided at the time of installation or download, or which
//  otherwise accompanies this software in either electronic or hard copy form.  
//
//////////////////////////////////////////////////////////////////////////////


#pragma once

#include "GcmpModel.h"

namespace gcmp
{

    class IDocument;
    class IDocumentInitializer;

    /// \brief 文件恢复信息
    class GCMP_MODEL_EXPORT IFileRestoreInformation
    {
    public:
        /// \brief 析构函数 
        /// \return 无
        virtual ~IFileRestoreInformation() { };

        /// \brief 返回文件名，如：文件1等 
        /// \return 文件名
        virtual std::wstring GetFileName() const = 0;

        /// \brief 返回指示文件的全路径 
        /// \return 指示文件的全路径
        virtual std::wstring GetFullFilePath() const = 0;
    };

    /// \brief 文档异常恢复失败类型
    enum class FileRestoreErrorType : int32_t
    {
        NoError = 0,  ///< 没有错误
        ReadOnly = 1, ///< 只读
        NotExisted = 2, ///<指示文件不存在
        OtherError = 3, ///< 其他错误
    };

    /// \brief 文档异常恢复返回的信息
    struct FileRestoreResult
    {
        FileRestoreResult()
        {
            RestoredDocument = nullptr;
            ErrorType = FileRestoreErrorType::NoError;
        }
        std::wstring IndicatorFilePath;    ///< 指示文档的全路径 
        FileRestoreErrorType ErrorType; ///< 失败类型
        IDocument* RestoredDocument; ///< 被恢复文档的指针
    };

    /// \brief 文档异常删除返回的信息
    struct FileDeleteResult
    {
        FileDeleteResult()
        {
            ErrorType = FileRestoreErrorType::NoError;
        }
        std::wstring IndicatorFilePath;    ///< 指示文档的全路径 
        FileRestoreErrorType ErrorType; ///< 失败类型
    };

    /// \brief 文档异常恢复工具类
    class GCMP_MODEL_EXPORT FileRestoreUtils final
    {
    public:
        /// \brief 判断是否启用文档恢复功能
        ///
        /// \return 是否启用文档恢复功能，true表示启用，false表示不启用
        static bool IsFileRestoreEnabled();

        /// \brief 设置是否启用文档恢复功能
        ///
        /// \param enableOrDisable 是否启用文档恢复功能
        /// \return void
        static void EnableFileRestore(bool enableOrDisable);

        /// \brief 给定文件路径，检查是否曾经异常退出过
        ///
        /// \param fullFilePath 文件路径
        /// \return bool 如果曾经异常退出过，返回true；否则返回false
        static bool ExitedAbnormally(const std::wstring& fullFilePath);

        /// \brief 给定文件路径，检查是否曾经异常退出过
        ///
        /// \param fullFilePath 文件路径
        /// \param indicatorfilefullpath 如果异常退出，填入indicatorfile全路径
        /// \return bool 如果曾经异常退出过，返回true；否则返回false
        static bool ExitedAbnormally(const std::wstring& fullFilePath, std::wstring* indicatorfilefullpath);

        /// \brief 得到异常退出的所有文件
        ///
        /// \param files 文件路径
        static void GetAllFilesExitedAbnormally(std::list<std::wstring>& files);        

        /// \brief 文件当前是否未被进程打开，并且文件发生过异常退出
        ///
        /// \param fullFilePath 文件路径
        /// \return bool 如果曾经异常退出过，返回true；否则返回false
        static bool ExitedAbnormallyNotOpenning(const std::wstring& fullFilePath);

        /// \brief 拷贝复现异常退出所需要的所有文件
        ///
        /// \param fullFilePath 项目文件路径
        /// \param targetpath 拷贝的目标路径
        /// \return bool 如果曾经异常退出过，返回true；否则返回false
        static bool PatchExitedAbnormallyDataToPath(const std::wstring& fullFilePath, const std::wstring& targetpath);

        /// \brief 设置文档恢复是否采用拷贝旧文件，在新文件上恢复的方式
        ///
        /// 是代表拷贝旧文件，之后的恢复和修改在拷贝出的新文件上进行；否代表恢复和之后的修改在旧文件上进行
        /// \param enableOrDisable 是否采用拷贝旧文件，在新文件上恢复的方式
        /// void 空
        static void EnableRestoreOnNewFile(bool enableOrDisable);

        /// \brief 判断文档恢复是否采用拷贝旧文件，在新文件上恢复的方式
        ///
        /// 采用拷贝旧文件，在新文件上恢复的方式情况下，需要调用以下SetRestoreNewFilePath(const std::wstring&, const std::wstring&)设置新文件全路径
        /// \return bool 文档恢复是否采用拷贝旧文件，在新文件上恢复的方式，true表示是，false表示不是
        static bool IsRestoreOnNewFileEnabled();

        /// \brief 当文档恢复采用拷贝旧文件，在新文件上恢复的方式时，设置新旧文件的路径
        ///
        /// 采用拷贝旧文件，在新文件上恢复的方式情况下需调用此接口
        /// 如果不调用，则打开文件时会打开失败，返回DocumentLoadError::FailToProcessFileForResotre
        /// \param originFilePath 原文件的路径
        /// \param newFilePath 新文件的路径
        /// \return bool 是否设置成功，true表示是，false表示不是
        static bool SetRestoreNewFilePath(const std::wstring& originFilePath, const std::wstring& newFilePath);

        /// \brief 获取崩溃恢复指示文件后缀，带"."
        /// \return 溃恢复指示文件后缀
        static const wchar_t * const GetIndicatorExtension();

        /// \brief 根据文件名判断是否是崩溃恢复指示文件
        ///
        /// \param candidate 判断的文件名称，含后缀，不含路径
        /// \param fileName 原来文件的名称，含后缀，不含路径
        /// \return 是-true;否-false
        static bool IsIndicatorFile(const std::wstring& candidate, const std::wstring& fileName);

    public:
        /// \brief 获取临时目录下所有异常退出的项目文件的信息 
        /// \return 异常退出的项目文件信息的列表
        static std::vector<OwnerPtr<IFileRestoreInformation>> GetFileRestoreInformations();

        /// \brief 根据文件信息删除临时文件
        /// \param informations 需要刪除的文件信息列表
        /// \return 返回删除失败的错误结果列表，如果全部删除成功，则列表的大小为0
        static std::vector<FileDeleteResult>  DeleteAbnormalFiles(const std::vector<OwnerPtr<IFileRestoreInformation>>& informations);

        /// \brief 根据文件信息恢复异常退出的文件
        /// \param documentInitializer 文档初始化指针
        /// \param informations 文件信息列表
        /// \return 返回文件恢复结果的列表
        static std::vector<FileRestoreResult> RestoreAbnormalFiles(IDocumentInitializer* documentInitializer, const std::vector<OwnerPtr<IFileRestoreInformation>>& informations);
    };
}
